home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrtools-1.10 / lib / cvt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-08  |  4.9 KB  |  212 lines

  1. /* @(#)cvt.c    1.3 99/09/08 Copyright 1998 J. Schilling */
  2. /*
  3.  *    Compatibility routines for 4.4BSD based C-libraries ecvt()/fcvt()
  4.  *    and a working gcvt() that is needed on 4.4BSD and GNU libc systems.
  5.  *
  6.  *    On 4.4BSD, gcvt() is missing, the gcvt() implementation from GNU libc
  7.  *    is not working correctly.
  8.  *
  9.  *    Neither __dtoa() nor [efg]cvt() are MT safe.
  10.  *
  11.  *    Copyright (c) 1998 J. Schilling
  12.  */
  13. /*
  14.  * This program is free software; you can redistribute it and/or modify
  15.  * it under the terms of the GNU General Public License as published by
  16.  * the Free Software Foundation; either version 2, or (at your option)
  17.  * any later version.
  18.  *
  19.  * This program is distributed in the hope that it will be useful,
  20.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22.  * GNU General Public License for more details.
  23.  *
  24.  * You should have received a copy of the GNU General Public License
  25.  * along with this program; see the file COPYING.  If not, write to
  26.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  27.  */
  28.  
  29. #include <stdxlib.h>
  30. #include <utypes.h>
  31. #include <standard.h>
  32.  
  33. #ifdef    HAVE_DTOA    /* 4.4BSD floating point implementation */
  34. extern    char *__dtoa    __PR((double value, int mode, int ndigit, int *decpt, int *sign, char **ep));
  35. #endif
  36.  
  37. #ifndef    HAVE_ECVT
  38. EXPORT    char *ecvt    __PR((double value, int ndigit, int *decpt, int *sign));
  39. #endif
  40. #ifndef    HAVE_FCVT
  41. EXPORT    char *fcvt    __PR((double value, int ndigit, int *decpt, int *sign));
  42. #endif
  43. #ifndef    HAVE_GCVT
  44. EXPORT    char *gcvt    __PR((double value, int ndigit, char *buf));
  45. #endif
  46.  
  47. #if    !defined(HAVE_ECVT) && defined(HAVE_DTOA)
  48. #define    HAVE_ECVT
  49. char *
  50. ecvt(value, ndigit, decpt, sign)
  51.     double    value;
  52.     int    ndigit;
  53.     int    *decpt;
  54.     int    *sign;
  55. {
  56. static    Uint    bufsize;
  57. static    char    *buf;
  58.     char    *bufend;
  59.     char    *ep;
  60.     char    *bp = __dtoa(value, 2, ndigit, decpt, sign, &ep);
  61.  
  62.     if (value == 0.0) {
  63.         /*
  64.          * Handle __dtoa()'s deviation from ecvt():
  65.          * 0.0 is converted to "0" instead of 'ndigit' zeroes.
  66.          * The string "0" is not allocated, so
  67.          * we need to allocate buffer to hold 'ndigit' zeroes.
  68.          */
  69.         if (bufsize < ndigit + 1) {
  70.             if (buf != (char *)0)
  71.                 free(buf);
  72.             bufsize = ndigit + 1;
  73.             buf = malloc(bufsize);
  74.         }
  75.         ep = bp = buf;
  76.     }
  77.  
  78.     /*
  79.      * Fill up trailing zeroes suppressed by __dtoa()
  80.      * From an internal __dtoa() comment:
  81.      *    Sufficient space is allocated to the return value
  82.      *    to hold the suppressed trailing zeros.
  83.      */
  84.     for (bufend = &bp[ndigit]; ep < bufend; )
  85.         *ep++ = '0';
  86.     *ep = '\0';
  87.  
  88.     return (bp);
  89. }
  90. #endif
  91.  
  92. #if    !defined(HAVE_FCVT) && defined(HAVE_DTOA)
  93. #define    HAVE_FCVT
  94. char *
  95. fcvt(value, ndigit, decpt, sign)
  96.     double    value;
  97.     int    ndigit;
  98.     int    *decpt;
  99.     int    *sign;
  100. {
  101. static    Uint    bufsize;
  102. static    char    *buf;
  103.     char    *bufend;
  104.     char    *ep;
  105.     char    *bp = __dtoa(value, 3, ndigit, decpt, sign, &ep);
  106.  
  107.     if (value == 0.0) {
  108.         /*
  109.          * Handle __dtoa()'s deviation from fcvt():
  110.          * 0.0 is converted to "0" instead of 'ndigit' zeroes.
  111.          * The string "0" is not allocated, so
  112.          * we need to allocate buffer to hold 'ndigit' zeroes.
  113.          */
  114.         if (bufsize < ndigit + 1) {
  115.             if (buf != (char *)0)
  116.                 free(buf);
  117.             bufsize = ndigit + 1;
  118.             buf = malloc(bufsize);
  119.         }
  120.         ep = bp = buf;
  121.         *decpt = 0;
  122.     }
  123.  
  124.     /*
  125.      * Fill up trailing zeroes suppressed by __dtoa()
  126.      * From an internal __dtoa() comment:
  127.      *    Sufficient space is allocated to the return value
  128.      *    to hold the suppressed trailing zeros.
  129.      */
  130.     for (bufend = &bp[*decpt + ndigit]; ep < bufend; )
  131.         *ep++ = '0';
  132.     *ep = '\0';
  133.  
  134.     return (bp);
  135. }
  136. #endif
  137.  
  138. #ifndef    HAVE_GCVT
  139. #define    HAVE_GCVT
  140. char *
  141. gcvt(number, ndigit, buf)
  142.     double    number;
  143.     int    ndigit;
  144.     char    *buf;
  145. {
  146.          int    sign;
  147.          int    decpt;
  148.     register char    *b;
  149.     register char    *rs;
  150.     register int    i;
  151.  
  152.     b = ecvt(number, ndigit, &decpt, &sign);
  153.     rs = buf;
  154.     if (sign)
  155.         *rs++ = '-';
  156.     for (i = ndigit-1; i > 0 && b[i] == '0'; i--)
  157.         ndigit--;
  158. #ifdef    V7_FLOATSTYLE
  159.     if ((decpt >= 0 && decpt-ndigit > 4) ||
  160. #else
  161.     if ((decpt >= 0 && decpt-ndigit > 0) ||
  162. #endif
  163.         (decpt < 0 && decpt < -3)) {    /* e-format */
  164.         decpt--;
  165.         *rs++ = *b++;
  166.         *rs++ = '.';
  167.         for (i = 1; i < ndigit; i++)
  168.             *rs++ = *b++;
  169.         *rs++ = 'e';
  170.         if (decpt < 0) {
  171.             decpt = -decpt;
  172.             *rs++ = '-';
  173.         } else {
  174.             *rs++ = '+';
  175.         }
  176.         if (decpt >= 100) {
  177.             *rs++ = decpt / 100 + '0';
  178.             decpt %= 100;
  179.         }
  180.         *rs++ = decpt / 10 + '0';
  181.         *rs++ = decpt % 10 + '0';
  182.     } else {                /* f-format */
  183.         if (decpt <= 0) {
  184.             if (*b != '0') {
  185. #ifndef    V7_FLOATSTYLE
  186.                 *rs++ = '0';
  187. #endif
  188.                 *rs++ = '.';
  189.             }
  190.             while (decpt < 0) {
  191.                 decpt++;
  192.                 *rs++ = '0';
  193.             }
  194.         }
  195.         for (i = 1; i <= ndigit; i++) {
  196.             *rs++ = *b++;
  197.             if (i == decpt)
  198.                 *rs++ = '.';
  199.         }
  200.         if (ndigit < decpt) {
  201.             while (ndigit++ < decpt)
  202.                 *rs++ = '0';
  203.             *rs++ = '.';
  204.         }
  205.     }
  206.     if (rs[-1] == '.')
  207.         rs--;
  208.     *rs = '\0';
  209.     return (buf);
  210. }
  211. #endif
  212.